/*
 * Copyright 2008 Lucas Tan.
 * This copyright notice must always remain intact whenever you use or distribute 
 * the source code contained in this file.
 * Any usage of any code in this file, either in derived work or
 * through the use of external linkage,
 * must always be credited with the author's name.
 * 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 * 
 * */
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace PassKeeper.Cryptography
{

	///
	/// <summary>
	/// Represents the base class from which all implementations of the 
	/// Advanced Encryption Standard (AES) must inherit.
	/// </summary>
	/// <remarks>The implementation must conform to the FIPS-197 specification at
	/// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
	/// </remarks>
	///
	public abstract class AES : SymmetricAlgorithm
	{
		private static readonly KeySizes[] s_legalKeySizes;
		private static readonly KeySizes[] s_legalBlockSizes;

		static AES()
		{
			/*128, 192 or 256 bits.*/
			s_legalKeySizes = new KeySizes[] { new KeySizes (128, 256,64)};
			
			/*128 bits only.*/
			s_legalBlockSizes = new KeySizes[] { new KeySizes (128,128,0)};
		}

		public new static AES Create()
		{
			/*Maintain the behavior of the parent class, even though this method
			 will always either never succeed or return null. 
			 Because this is an abstract class.*/
			return Create(typeof(AES).FullName);
		}

		public new static AES Create(string name)
		{
			/*Borrow their code.*/
			return (AES)SymmetricAlgorithm.Create(name);
		}

		protected AES() : base()
		{
			/*Set the allowed values first.*/
			base.LegalKeySizesValue = s_legalKeySizes;
			base.LegalBlockSizesValue = s_legalBlockSizes;

			/* Always fixed.*/
			base.BlockSizeValue = 
				base.FeedbackSizeValue =128;

			/*Default values.*/
			base.KeySizeValue = 256;

			/*Set to CBC, which is the default cipher mode in W3C's
			 XML Encryption standard.*/
			base.ModeValue = CipherMode.CBC;
			base.PaddingValue = PaddingMode.ISO10126;
		}

		/// <summary>
		/// Gets or sets the feedback size for use in the <see cref="CipherMode.CFB">CFB</see>
		/// <see cref="CipherMode.OFB">OFB</see> cipher modes.
		/// </summary>
		/// <value>The feedback size is fixed to be the same as the block size.
		/// There is no point in modifying it.</value>
		public sealed override int FeedbackSize
		{
			get
			{
				return base.FeedbackSize;
			}
			set
			{
				if (value != 128)
				{
					throw new ArgumentException("Must be the same as block size.", "value");
				}

				/*No need to update.*/
				/*base.FeedbackSize = value;*/
			}
		}
	}
} 
